/*
 * @(#)TransferFormatter.java	1.0 2007-11-26
 *
 * Copyright All rights reserved.
 * Use is subject to license terms.
 */
package com.gopay.bis.icbc.expay.operation;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlbeans.XmlException;

import cn.com.infosec.util.Base64;

import com.gopay.bis.common.util.TransUtil;
import com.gopay.bis.common.util.constants.Constants4BankSwitch;
import com.gopay.common.constants.bank.IcbcConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.icbc.bcdl.pay.IcbcMessageData;
import com.gopay.common.domain.bank.icbc.bcdl.pay.IcbcPacketMessage;
import com.gopay.common.domain.bank.icbc.expay.IcbcExpayCmsEbPubReq;
import com.gopay.common.exception.GopayException;

/**
 * TransferFormatter.java
 * <p>
 * Created on 2007-11-26 Modification history
 * <p>
 * Query transfer information from bank ICBC.
 * 
 * @author Richard Chen
 * @version 1.0
 * @since 1.0
 */

public class Transformer {
//	HttpTransportForSign signTransport;
	/** Logger for logging information. */
	protected Log log = LogFactory.getLog(this.getClass());
	/** XML文件头. */
	protected static final String XMLHEADER = "<?xml version=\"1.0\" encoding=\"GBK\" ?>\n";
	protected static final String SUC = "0";
	/** Encoding. */
	protected static final String ENCODING = "GBK";
	/** new Initiate capacity. */
	private static final int INIT_CAPACITY = 10;
	/** 版本号. */
	protected String version = null;
	/** 汇款账号. */
	protected String payDepAcc = null;
	/** 收款人地区代码. */
	protected String recAreaCode = null;
	/** 汇款速度. */
	protected String payType = null;
	/** 提交人ID. */
	protected String submitLogId = null;
	/** 企业代码. */
	protected String userId = null;
	/** 汇款单位. */
	protected String payDepName = null;
	/** 付款人地区代码. */
	protected String areaCode = null;
	/** 汇款单位开户行. */
	protected String payDepBranch = null;
	/** 币种. */
	protected String accountCur = null;
	/** 付款人账户地区名. */
	protected String areaName = null;
	/** 账号. */
	protected String acNo = null;
	/** 商城账号. */
	protected String shopacct = null;
	/** 商城类型. */
	protected String shopType = null;
	/** 支付指令提交交易代码. */
	protected String transCode = null;
	/** 财务室指令提交交易代码. */
	protected String qtransCode = null;
	/** b2b交易代码. */
	protected String b2bTransCode = null;
	/** b2c交易代码. */
	protected String b2cTransCode = null;
	/** 集团CIS号. */
	protected String cis = null;
	/** 归属银行编号. */
	protected String bankCode = null;
	/** 证书ID. */
	protected String id = null;
	/** 商城代码. */
	protected String shopCode = null;
	/** 商城账号. */
	protected String shopAcct = null;

	private static final String SEND_XML_NAMESPACE = "http://res.trans.doc.operation.bcdl.icbc.bis.gopay.com";
	private static final String RECEIVED_XML_NAMESPACE = "<CMS xmlns=\"http://res.trans.doc.operation.bcdl.icbc.bis.gopay.com\">";
	
	
	/**
	 * 取得发送NetSafeClient的请求参数.
	 * 
	 * @param obj
	 *            报文.
	 * @param formatRes
	 *            format res.
	 * @return map.
	 * @throws GopayException
	 */
	public static Map getIssueNCParaMap(Object obj, Object formatRes,String url)
			throws GopayException {
		byte[] formatResByte = (byte[]) formatRes;
		try {
			formatResByte = new String(formatResByte).getBytes("GBK");
			IcbcExpayCmsEbPubReq msg=(IcbcExpayCmsEbPubReq) obj;
			String reqData = getSignature(formatResByte,url);
			// 组织提交工行所需form的field域及其值，报文体由IcbcConstants.REQ_DATA指定
			Map requestParaMap = new HashMap(INIT_CAPACITY);
			// 证书ID
			requestParaMap.put(IcbcConstants.USER_ID, msg.getId());
			// 请求时间
			requestParaMap.put(IcbcConstants.SEND_TIME, TransUtil.getSendTime());
			// 版本号（不同版本号对应的接口格式不同，请参考具体交易的接口文档)
			requestParaMap.put(IcbcConstants.VERSION, "0.0.1.0");
			// 交易码
			requestParaMap.put(IcbcConstants.TRANS_CODE, msg.getTransCode());
			// 客户的归属单位
			requestParaMap.put(IcbcConstants.BANK_CODE, msg.getBankCode());
			// 客户的归属编码
			requestParaMap.put(IcbcConstants.GROUP_CIS, msg.getCis());
			// 客户的证书ID（无证书客户可空)
			requestParaMap.put(IcbcConstants.ID, msg.getId());
			// 客户的指令包序列号（由客户ERP系统产生，不可重复)
			requestParaMap.put(IcbcConstants.PACKAGE_ID, msg.getfSeqno());
			// 客户的证书公钥信息（进行BASE64编码；NC客户送空)
			requestParaMap.put(IcbcConstants.CERT, "");
			// 客户的xml请求数据,由相应的Formatter生成
			requestParaMap.put(IcbcConstants.REQ_DATA, reqData);
			return requestParaMap;
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E6046);
		}
	}
	
	/**
     * 取得批量发送NetSafeClient的请求参数.
     * 
     * @param obj
     * @param formatRes
     * @return
     * @throws GopayException
     */
    public Map getPacketIssueNCParaMap(Object obj, Object formatRes)throws GopayException {
        byte[] formatResByte = (byte[]) formatRes;
        try {
            formatResByte = new String(formatResByte).getBytes("GBK");
        
        IcbcExpayCmsEbPubReq msg = (IcbcExpayCmsEbPubReq) obj;
        String reqData = null;
        reqData = new String(formatResByte);
        
        // 组织提交工行所需form的field域及其值，报文体由IcbcConstants.REQ_DATA指定
        Map requestParaMap = new HashMap(INIT_CAPACITY);
        // 证书ID
        requestParaMap.put(IcbcConstants.USER_ID, msg.getId());
        // 请求时间
        requestParaMap.put(IcbcConstants.SEND_TIME, TransUtil.getSendTime());
        // 版本号（不同版本号对应的接口格式不同，请参考具体交易的接口文档)
        requestParaMap.put(IcbcConstants.VERSION, "0.0.1.0");
        // 交易码
        requestParaMap.put(IcbcConstants.TRANS_CODE, msg.getTransCode());
        // 客户的归属单位
        requestParaMap.put(IcbcConstants.BANK_CODE, msg.getBankCode());
        // 客户的归属编码
        requestParaMap.put(IcbcConstants.GROUP_CIS, msg.getCis());
        // 客户的证书ID（无证书客户可空)
        requestParaMap.put(IcbcConstants.ID, msg.getId());
        // 客户的指令包序列号（由客户ERP系统产生，不可重复)
        requestParaMap.put(IcbcConstants.PACKAGE_ID, msg.getfSeqno());
        // 客户的证书公钥信息（进行BASE64编码；NC客户送空)
        requestParaMap.put(IcbcConstants.CERT, "");
        // 客户的xml请求数据,由相应的Formatter生成
        requestParaMap.put(IcbcConstants.REQ_DATA, reqData);
        return requestParaMap;
        } catch (UnsupportedEncodingException e1) {
            log.error("Queryformer getPacketIssueNCParaMap error: ", e1);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6050);
        }
    }
	
    /**
     * 取得批量发送NetSafeClient的请求参数.
     * 
     * @param obj
     * @param formatRes
     * @param url
     * @return
     * @throws GopayException
     */
    public Map getPacketIssueNCParaMap(Object obj, Object formatRes,String url)
            throws GopayException {
        byte[] formatResByte = (byte[]) formatRes;
        try {
            formatResByte = new String(formatResByte).getBytes("GBK");
            IcbcPacketMessage msg = (IcbcPacketMessage) obj;
            String reqData = getSignature(formatResByte,url);
            // 组织提交工行所需form的field域及其值，报文体由IcbcConstants.REQ_DATA指定
            Map requestParaMap = new HashMap(INIT_CAPACITY);
            // 证书ID
            requestParaMap.put(IcbcConstants.USER_ID, msg.getId());
            // 请求时间
            requestParaMap.put(IcbcConstants.SEND_TIME, TransUtil.getSendTime());
            // 版本号（不同版本号对应的接口格式不同，请参考具体交易的接口文档)
            requestParaMap.put(IcbcConstants.VERSION, msg.getVersion());
            // 交易码
            requestParaMap.put(IcbcConstants.TRANS_CODE, msg.getTransCode());
            // 客户的归属单位
            requestParaMap.put(IcbcConstants.BANK_CODE, msg.getBankCode());
            // 客户的归属编码
            requestParaMap.put(IcbcConstants.GROUP_CIS, msg.getCis());
            // 客户的证书ID（无证书客户可空)
            requestParaMap.put(IcbcConstants.ID, msg.getId());
            // 客户的指令包序列号（由客户ERP系统产生，不可重复)
            requestParaMap.put(IcbcConstants.PACKAGE_ID, msg.getPacketNo());
            // 客户的证书公钥信息（进行BASE64编码；NC客户送空)
            requestParaMap.put(IcbcConstants.CERT, "");
            // 客户的xml请求数据,由相应的Formatter生成
            requestParaMap.put(IcbcConstants.REQ_DATA, reqData);
            return requestParaMap;
        } catch (UnsupportedEncodingException e1) {
            log.error("Transformer getPacketIssueNCParaMap error: ", e1);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6046);
        }
    }

	/**
	 * Sign the plainText by the ICBC NC Server.
	 * 
	 * @param plainText
	 *            plainText in a XML style confirm to the specification of ICBC
	 *            API．
	 * @return signature of plainText.
	 * @throws GopayException 
	 */
	private static  String getSignature(byte[] plainText,String url) throws GopayException {
	    try {
	        HttpTransportForSign signTransport = new HttpTransportForSign();
            signTransport.setUrl(url);
            byte[] resFromSignatureServer = (byte[]) signTransport
                    .submit(plainText);
            String msg = new String(resFromSignatureServer);
            String signature = TransUtil.getMsgField(
                    IcbcConstants.RETURN_SIGN_BEGIN_TAG,
                    IcbcConstants.RETURN_SIGN_END_TAG, msg);
            return signature;
        } catch (RuntimeException er) {
           // log.error(" icbc bcdl  eft getSignature error: ", er);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6082);
        }
	}

	/**
	 * 当参数值是empty时返回空格
	 */
	public String getSpaceIfEmpty(String value) {
		return StringUtils.isEmpty(value) ? " " : value;
	}

	/**
	 * Set account currency.
	 * 
	 * @param accountCur
	 *            the accountCur to set.
	 */
	public void setAccountCur(String accountCur) {
		this.accountCur = accountCur;
	}

	/**
	 * Set area code.
	 * 
	 * @param areaCode
	 *            the areaCode to set.
	 */
	public void setAreaCode(String areaCode) {
		this.areaCode = areaCode;
	}

	/**
	 * Set area name.
	 * 
	 * @param areaName
	 *            the areaName to set.
	 */
	public void setAreaName(String areaName) {
		this.areaName = areaName;
	}

	/**
	 * Set pay deptment branch.
	 * 
	 * @param payDepBranch
	 *            the payDepBranch to set.
	 */
	public void setPayDepBranch(String payDepBranch) {
		this.payDepBranch = payDepBranch;
	}

	/**
	 * Set pay deptment name.
	 * 
	 * @param payDepName
	 *            the payDepName to set.
	 */
	public void setPayDepName(String payDepName) {
		this.payDepName = payDepName;
	}

	/**
	 * Set pay type.
	 * 
	 * @param payType
	 *            the payType to set.
	 */
	public void setPayType(String payType) {
		this.payType = payType;
	}

	/**
	 * Set receive area code.
	 * 
	 * @param recAreaCode
	 *            the recAreaCode to set.
	 */
	public void setRecAreaCode(String recAreaCode) {
		this.recAreaCode = recAreaCode;
	}

	/**
	 * Set pay deptment account.
	 * 
	 * @param payDepAcc
	 *            the payDepAcc to set.
	 */
	public void setPayDepAcc(String payDepAcc) {
		this.payDepAcc = payDepAcc;
	}

	/**
	 * Set submit log id.
	 * 
	 * @param submitLogId
	 *            the submitLogId to set.
	 */
	public void setSubmitLogId(String submitLogId) {
		this.submitLogId = submitLogId;
	}

	/**
	 * Set user id.
	 * 
	 * @param userID
	 *            the userId to set.
	 */
	public void setUserId(String userID) {
		this.userId = userID;
	}

	/**
	 * Set ac no.
	 * 
	 * @param acNo
	 *            the acNo to set
	 */
	public void setAcNo(String acNo) {
		this.acNo = acNo;
	}

	public Log getLog() {
		return log;
	}

	public void setLog(Log log) {
		this.log = log;
	}

	public String getShopacct() {
		return shopacct;
	}

	public void setShopacct(String shopacct) {
		this.shopacct = shopacct;
	}

	public String getPayDepAcc() {
		return payDepAcc;
	}

	public String getRecAreaCode() {
		return recAreaCode;
	}

	public String getPayType() {
		return payType;
	}

	public String getSubmitLogId() {
		return submitLogId;
	}

	public String getUserId() {
		return userId;
	}

	public String getPayDepName() {
		return payDepName;
	}

	public String getAreaCode() {
		return areaCode;
	}

	public String getPayDepBranch() {
		return payDepBranch;
	}

	public String getAccountCur() {
		return accountCur;
	}

	public String getAreaName() {
		return areaName;
	}

	public String getAcNo() {
		return acNo;
	}

	public String getCis() {
		return cis;
	}

	public void setCis(String cis) {
		this.cis = cis;
	}

	public String getBankCode() {
		return bankCode;
	}

	public void setBankCode(String bankCode) {
		this.bankCode = bankCode;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getShopAcct() {
		return shopAcct;
	}

	public void setShopAcct(String shopAcct) {
		this.shopAcct = shopAcct;
	}

	public static String getXmlheader() {
		return XMLHEADER;
	}

	public static String getEncoding() {
		return ENCODING;
	}

	public String getShopType() {
		return shopType;
	}

	public void setShopType(String shopType) {
		this.shopType = shopType;
	}

	public String getTransCode() {
		return transCode;
	}

	public void setTransCode(String transCode) {
		this.transCode = transCode;
	}

	public String getQtransCode() {
		return qtransCode;
	}

	public void setQtransCode(String qtransCode) {
		this.qtransCode = qtransCode;
	}

	public String getB2bTransCode() {
		return b2bTransCode;
	}

	public void setB2bTransCode(String b2bTransCode) {
		this.b2bTransCode = b2bTransCode;
	}

	public String getB2cTransCode() {
		return b2cTransCode;
	}

	public void setB2cTransCode(String b2cTransCode) {
		this.b2cTransCode = b2cTransCode;
	}

	public String getShopCode() {
		return shopCode;
	}

	public void setShopCode(String shopCode) {
		this.shopCode = shopCode;
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}

//	public HttpTransportForSign getSignTransport() {
//		return signTransport;
//	}
//
//	public void setSignTransport(HttpTransportForSign signTransport) {
//		this.signTransport = signTransport;
//	}

}
